package org.offsync.util

import java.io.Closeable
import org.offsync.rich._

class Disposer extends DisposableBase {
  private var list: List[Disposable] = Nil

  def cancel(): Unit = lock.synchronized {
    list = Nil
  }
  
  def closes[C <: { def close(): Unit }](closeable: C): C = {
    disposes(new Disposable {
      override def disposeState = DisposeState.Unknown
      
      override def dispose(): Unit = closeable.close()

      override def waitDisposed(
          deadline: Time): Unit = { }
    })

    return closeable
  }
  
  def dependsOn[U](f: => U): U = try f catch { case e => this.dispose(); throw e }

  def dependsOnAndDisposes[U <: Disposable](f: => U): U = {
    try disposes(f) catch { case e => this.dispose(); throw e }
  }

  def disposes[D <: Disposable](disposable: => D): D = {
    lock.synchronized {
      disposableBaseState.requireLive()
      
      val disposableInstance = try {
        disposable
      } catch { case e =>
        this.dispose()
        throw e.wrap()
      }
  
      list = disposableInstance :: list
      
      return disposableInstance
    }
  }
  
  override def onDispose(): Unit = {
    list.foreach { disposable =>
      try {
        disposable.dispose()
      } catch { case e =>
      }
    }
    super.onDispose()
  }
  
  override def waitDisposed(
      deadline: Time): Unit = {
    list.foreach { disposable =>
      try {
        disposable.waitDisposed(deadline)
      } catch { case e =>
      }
    }
    super.waitDisposed()
  }
}
